package com.desay.pangoo.itmt.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import cn.hutool.core.util.ArrayUtil;

public class CompareObjUtil {
	private CompareObjUtil() {

	}

	/** 不需要比较的字段 */
	protected static String[] ignoreFiled = new String[] { "id", "version", "createTime", "modifyTime", "creator",
			"updator" };

	@SuppressWarnings("unchecked")
	public static <T extends Serializable> T clone(T obj) {
		T cloneObj = null;
		try {
			// 写入字节流
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			ObjectOutputStream obs = new ObjectOutputStream(out);
			obs.writeObject(obj);
			obs.close();

			// 分配内存，写入原始对象，生成新对象
			ByteArrayInputStream is = new ByteArrayInputStream(out.toByteArray());
			ObjectInputStream os = new ObjectInputStream(is);
			cloneObj = (T) os.readObject();
			os.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return cloneObj;
	}

	/**
	 * 比较对象属性差值
	 * 
	 * @param beforeObj
	 * @param afterObj
	 * @return
	 * @throws Exception
	 */
	public static List<Comparison> compareObj(Object beforeObj, Object afterObj) throws Exception {

		List<Comparison> differents = new ArrayList<>();
		if (beforeObj == null || afterObj == null) {
			throw new Exception("对象不能为空");
		}
		if (!beforeObj.getClass().isAssignableFrom(afterObj.getClass())) {
			throw new Exception("两个对象不相同，无法比较");
		}

		// 取出属性
		Field[] beforeFields = beforeObj.getClass().getDeclaredFields();
		Field[] afterFields = afterObj.getClass().getDeclaredFields();
		AccessibleObject.setAccessible(beforeFields, true);
		AccessibleObject.setAccessible(afterFields, true);

		// 遍历取出差异值
		if (beforeFields != null && beforeFields.length > 0) {
			for (int i = 0; i < beforeFields.length; i++) {
				if (ArrayUtil.contains(ignoreFiled, beforeFields[i].getName())) {
					continue;
				}
				Object beforeValue = beforeFields[i].get(beforeObj);
				Object afterValue = afterFields[i].get(afterObj);
				if ((beforeValue != null && !"".equals(beforeValue) && !beforeValue.equals(afterValue))
						|| ((beforeValue == null || "".equals(beforeValue)) && afterValue != null
								&& !"".equals(afterValue))) {
					Comparison comparison = new Comparison();
					comparison.setField(beforeFields[i].getName());
					comparison.setBefore(beforeValue);
					comparison.setAfter(afterValue);
					differents.add(comparison);
				}
			}
		}
		return differents;
	}
}
